package map;

//TODO: NEEDS IMPROVED COMMENTS

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.Scrollable;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

@SuppressWarnings("serial")
public class MapManipulationPanel extends JPanel
{
    private MapDisplayPanel mapDisplayPanel;

    private JTabbedPane tabbedPane;
    private MoveItemsPanel moveItemsPanel;
    private AddItemsPanel addItemsPanel;
    private EditTerrainPanel editTerrainPanel;

    public MapManipulationPanel(MapDisplayPanel mapDisplayPanel)
    {
        this.mapDisplayPanel = mapDisplayPanel;
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(3, 1));
        this.setLayout(new BorderLayout());

        moveItemsPanel = new MoveItemsPanel();
        addItemsPanel = new AddItemsPanel(mapDisplayPanel);
        editTerrainPanel = new EditTerrainPanel(mapDisplayPanel);

        tabbedPane = new JTabbedPane();
        tabbedPane.setPreferredSize(new Dimension(1, 100));
        tabbedPane.addChangeListener(new MapManipulationPanelChangeListener());
        tabbedPane.setBackground(Color.BLACK);
        tabbedPane.setForeground(Color.MAGENTA);
        tabbedPane.addTab("Move Items", null, moveItemsPanel, "Move Items");
        JScrollPane p = new JScrollPane(addItemsPanel);
        p.getViewport().setBackground(Color.BLACK);
        p.getViewport().setOpaque(true);
        p.getViewport().addComponentListener(new ResizeListener(addItemsPanel));
        tabbedPane.addTab("Add Items", null, p, "Add Items");
        p = new JScrollPane(editTerrainPanel);
        p.getViewport().setBackground(Color.BLACK);
        p.getViewport().setOpaque(true);
        p.getViewport().addComponentListener(new ResizeListener(editTerrainPanel));
        tabbedPane.addTab("Edit Terrain", null, p, "Edit Terrain");
        tabbedPane.addTab("Other Tools", null, new OtherToolsPanel(),
                "Edit Terrain");

        switch (mapDisplayPanel.getManipulationMode())
        {
        case MapDisplayPanel.MOVE_ITEMS_MODE:
            tabbedPane.setSelectedIndex(0);
            break;
        case MapDisplayPanel.ADD_ITEMS_MODE:
            tabbedPane.setSelectedIndex(1);
            break;
        case MapDisplayPanel.EDIT_TERRAIN_MODE:
            tabbedPane.setSelectedIndex(2);
            break;
        }
        add(tabbedPane, BorderLayout.CENTER);
        add(panel, BorderLayout.WEST);
        validate();
        repaint();
    }

    private class MoveItemsPanel extends JPanel
    {
    }

    private class AddItemsPanel extends JPanel implements Scrollable
    {
        public AddItemsPanel(MapDisplayPanel display)
        {
            FlowLayout flowLayout = new ModifiedFlowLayout();
            flowLayout.setAlignment(FlowLayout.LEFT);
            setLayout(flowLayout);
            ButtonGroup group = new ButtonGroup();
            for (MapLibraryItemEntry item : display.getMap().getLibrary()
                    .getItemList())
            {
                ItemSelectButton button = new ItemSelectButton(item);
                add(button);
                group.add(button);
            }
            setBackground(Color.BLACK);
            setOpaque(true);
        }

        public void paintComponent(Graphics g)
        {
            g.setColor(getBackground());
            g.fillRect(0, 0, getWidth() + 5000, getHeight() + 5000);
            super.paintComponent(g);
        }

        // Makes Panel Scrollable
        public Dimension getPreferredScrollableViewportSize()
        {
            return getPreferredSize();
        }

        public int getScrollableBlockIncrement(Rectangle arg0, int arg1,
                int arg2)
        {
            return 100;
        }

        public boolean getScrollableTracksViewportHeight()
        {
            return false;
        }

        public boolean getScrollableTracksViewportWidth()
        {
            return false;
        }

        public int getScrollableUnitIncrement(Rectangle arg0, int arg1, int arg2)
        {
            return 10;
        }
    }

    private class EditTerrainPanel extends JPanel implements Scrollable
    {
        public EditTerrainPanel(MapDisplayPanel display)
        {
            FlowLayout flowLayout = new ModifiedFlowLayout();
            flowLayout.setAlignment(FlowLayout.LEFT);
            setLayout(flowLayout);
            ButtonGroup group = new ButtonGroup();
            for (MapLibraryTerrainEntry terrain : display.getMap().getLibrary()
                    .getTerrainList())
            {
                TerrainSelectButton button = new TerrainSelectButton(terrain);
                add(button);
                group.add(button);
            }
            setBackground(Color.BLACK);
            setOpaque(true);
        }

        public void paintComponent(Graphics g)
        {
            g.setColor(getBackground());
            g.fillRect(0, 0, getWidth() + 5000, getHeight() + 5000);
            super.paintComponent(g);
        }

        // Makes Panel Scrollable
        public Dimension getPreferredScrollableViewportSize()
        {
            return super.getPreferredSize();
        }

        public int getScrollableBlockIncrement(Rectangle arg0, int arg1,
                int arg2)
        {
            return 100;
        }

        public boolean getScrollableTracksViewportHeight()
        {
            return false;
        }

        public boolean getScrollableTracksViewportWidth()
        {
            return false;
        }

        public int getScrollableUnitIncrement(Rectangle arg0, int arg1, int arg2)
        {
            return 10;
        }
    }

    private class OtherToolsPanel extends JPanel
    {
        JTextField width = null;
        JTextField height = null;

        public OtherToolsPanel()
        {
            FlowLayout flowLayout = new ModifiedFlowLayout();
            flowLayout.setAlignment(FlowLayout.LEFT);
            setLayout(flowLayout);

            JPanel innerContainer = new JPanel();
            innerContainer.setLayout(new GridLayout(2, 1));
            add(innerContainer);

            JPanel firstTwoButtons = new JPanel();
            firstTwoButtons.setLayout(new FlowLayout());
            JButton clearButton = new JButton("Clear Map");
            clearButton.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    mapDisplayPanel.getMap().data.clear();
                    mapDisplayPanel.repaint();
                }
            });
            firstTwoButtons.add(clearButton);
            JButton randomFillButton = new JButton("Random Fill");
            randomFillButton.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    mapDisplayPanel.getMap().randomFill();
                    mapDisplayPanel.repaint();
                }
            });
            firstTwoButtons.add(randomFillButton);

            innerContainer.add(firstTwoButtons);

            JPanel dimensionChanger = new JPanel();
            dimensionChanger.setLayout(new FlowLayout());
            JButton changeDimensions = new JButton("Change Dimensions");
            changeDimensions.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e)
                {
                    mapDisplayPanel.getMap().data.setDimensions(
                            Integer.parseInt(width.getText()),
                            Integer.parseInt(height.getText()));
                    mapDisplayPanel.repaint();
                }
            });
            width = new JTextField(3);
            height = new JTextField(3);
            dimensionChanger.add(changeDimensions);
            dimensionChanger.add(width);
            dimensionChanger.add(height);

            innerContainer.add(dimensionChanger);
            /*
             * FlowLayout flowLayout = new FlowLayout();
             * flowLayout.setAlignment(FlowLayout.LEFT); setLayout(flowLayout);
             * ButtonGroup group = new ButtonGroup(); for(MapLibraryTerrainEntry
             * terrain : display.getMapData().getLibrary().getTerrainList()) {
             * TerrainSelectButton button = new TerrainSelectButton(terrain);
             * add(button); group.add(button); } setBackground(Color.BLACK);
             */
        }
    }

    private class TerrainSelectButton extends JRadioButton
    {
        MapLibraryTerrainEntry entry;

        public TerrainSelectButton(MapLibraryTerrainEntry entry)
        {
            super(entry.getName());
            this.entry = entry;
            setToolTipText(entry.getName());
            setSize(44, 44);
            setPreferredSize(new Dimension(44, 44));
            addActionListener(new TerrainButtonListener());
        }

        public void paintComponent(Graphics g)
        {
            g.setColor(Color.BLUE);
            if (isSelected())
                g.setColor(Color.YELLOW);
            g.fillRect(0, 0, 44, 44);
            g.setColor(Color.BLACK);
            g.fillRect(2, 2, 40, 40);
            g.drawImage(entry.getImage(), 3, 3, 38, 38, this);
        }

        private class TerrainButtonListener implements ActionListener
        {
            public void actionPerformed(ActionEvent arg0)
            {
                mapDisplayPanel.setAddTerrain(entry.getID());
                getParent().repaint();
            }
        }
    }

    private class ItemSelectButton extends JRadioButton
    {
        MapLibraryItemEntry entry;

        public ItemSelectButton(MapLibraryItemEntry entry)
        {
            super(entry.getName());
            this.entry = entry;
            setToolTipText(entry.getName());
            setSize(44, 44);
            setPreferredSize(new Dimension(44, 44));
            addActionListener(new TerrainButtonListener());
        }

        public void paintComponent(Graphics g)
        {
            g.setColor(Color.BLUE);
            if (isSelected())
                g.setColor(Color.YELLOW);
            g.fillRect(0, 0, 44, 44);
            g.setColor(Color.BLACK);
            g.fillRect(2, 2, 40, 40);
            g.drawImage(entry.getImage(), 3, 3, 38, 38, this);
        }

        private class TerrainButtonListener implements ActionListener
        {
            public void actionPerformed(ActionEvent arg0)
            {
                mapDisplayPanel.setAddItem(entry.getID());
                getParent().repaint();
            }
        }
    }

    private class MapManipulationPanelChangeListener implements ChangeListener
    {
        @Override
        public void stateChanged(ChangeEvent e)
        {
            switch (tabbedPane.getSelectedIndex())
            {
            case 0:
                mapDisplayPanel
                        .setManipulationMode(MapDisplayPanel.MOVE_ITEMS_MODE);
                break;
            case 1:
                mapDisplayPanel
                        .setManipulationMode(MapDisplayPanel.ADD_ITEMS_MODE);
                break;
            case 2:
                mapDisplayPanel
                        .setManipulationMode(MapDisplayPanel.EDIT_TERRAIN_MODE);
                break;
            default:
                mapDisplayPanel.setManipulationMode(-1);
                break;
            }
        }
    }

    public class ModifiedFlowLayout extends FlowLayout
    {
        public ModifiedFlowLayout()
        {
            super();
        }

        public Dimension minimumLayoutSize(Container target)
        {
            return computeSize(target);
        }

        public Dimension preferredLayoutSize(Container target)
        {
            return computeSize(target);
        }

        private Dimension computeSize(Container target)
        {
            synchronized (target.getTreeLock())
            {
                int hgap = getHgap();
                int vgap = getVgap();
                int width = target.getParent().getWidth();

                Insets insets = target.getInsets();
                if (insets == null)
                    insets = new Insets(0, 0, 0, 0);

                int x = width - (insets.left + insets.right + hgap * 2);
                int y = insets.top;
                int n = target.getComponentCount();
                if (n > 0 && target.getComponent(0).getWidth() > 0)
                {
                    Component c = target.getComponent(0);
                    int cols = (x - hgap) / (c.getWidth() + hgap);
                    int rows = (int) Math.ceil((double) n / cols);
                    y = insets.top + rows * c.getHeight() + insets.bottom
                            + (rows + 1) * vgap;
                }
                return new Dimension(x, y);
            }
        }
    }
    
    private class ResizeListener extends ComponentAdapter
    {
        JPanel panel;
        
        public ResizeListener(JPanel panel)
        {
            this.panel = panel;
        }

        public void componentResized(ComponentEvent arg0)
        {
            panel.revalidate();
            panel.repaint();
        }
    }
}
